Interview Playbook [Front-End]

Waymo TPS ยท ~45โ€“60 min ยท budget every step
Same skeleton as the coding playbook, adapted for "build this component/board/widget" problems. Time budgets assume a 45-minute problem inside a 60-minute call. The #1 reported failure on the Waymo Battleship question was burning 15+ minutes on rules clarification and running out of implementation time โ€” you drive the clock, not the interviewer.
1
Clarify how it looks
~3 min
"Let me confirm the visual first: an Nร—M grid of cells, plus a status panel below?"
  • Sketch the layout in words (or a quick comment block): what's on screen, where.
  • Dimensions: fixed size or configurable? Hardcoding 10ร—10 is usually fine โ€” ask.
  • Visual states per element: what does each cell/row/item look like in each state?
  • What must be displayed vs what's decoration. Skip styling polish unless asked.
  • Confirm CSS effort level: "Is basic CSS grid layout enough, or does styling matter here?"
2
Pin down the behavior
~4 min
"Three states per cell, click cycles empty โ†’ red โ†’ white โ†’ empty, ship is sunk when all its cells are red โ€” correct?"
  • State the rules back as one crisp sentence per interaction and get a yes/no. Closed questions, not open ones.
  • Enumerate every user action: click, double-click same element, type, submit, reset.
  • Derived outcomes: what's computed from state (winner, sunk, filtered count) and when it updates.
  • Edge interactions: clicking twice, clicking outside valid targets, empty input, rapid clicks.
  • Ask what's out of scope: persistence on refresh, animations, keyboard support โ€” usually no, confirm and move on.
  • Hard stop: if you're past ~7 total minutes of clarifying, propose assumptions out loud and start.
3
Design state before JSX
~5 min
"My state is one 2D array of cell states. Everything else โ€” sunk status, winner โ€” I derive during render."
  • Minimal state rule: store only what the user changes. If it can be computed from other state, derive it โ€” never store it.
  • Write the state shape as a type first: type Cell = 'empty'|'hit'|'miss', cells: Cell[][].
  • Static config (ship positions, options list) is not state โ€” a plain constant outside the component.
  • useState vs useReducer: one or two independent values โ†’ useState. Multiple transitions on one structure (game moves, undo) โ†’ useReducer, and say why: "one pure function owns all transitions, easy to test."
  • State lives in the top component; children get values + callbacks. Say "unidirectional data flow" out loud.
4
Component tree + plan
~3 min
"I'll do Board owning state, Cell as a dumb clickable, Status deriving from state. Sound right before I code?"
  • Name 2โ€“4 components max: <Board/>, <Cell/>, <Status/>. Don't over-split.
  • For each: props in, events out. Cell gets (state, onClick), nothing else.
  • State the build order: static render โ†’ click handler โ†’ derived status โ†’ polish. Working > complete.
  • Get the nod from the interviewer before typing โ€” course-correct here, not after 50 lines.
5
Code in layers, out loud
~20 min
"First I'll render the static grid from state so we can see something, then wire clicks."
  • Layer 1 โ€” static render: map state to JSX. Grid: cells.map((row,r) => row.map((cell,c) => ...)) inside display:grid. Stable keys (`${r}-${c}` is fine for a fixed grid).
  • Layer 2 โ€” interaction: one handler, immutable update. Never mutate: copy the row you touch.
  • Layer 3 โ€” derived UI: compute sunk/winner/filtered list in render body or useMemo, then display it.
  • Controlled inputs: value + onChange together, always.
  • Narrate as you type. Meaningful names. Don't chase CoderPad's missing JSX formatter โ€” indent by hand, add // @ts-nocheck if TS squiggles distract you.
// the immutable 2D update โ€” know this cold
setCells(prev => prev.map((row, ri) =>
  ri !== r ? row
  : row.map((cell, ci) => ci !== c ? cell : nextState(cell))
));
6
Test, then talk performance
~8 min
"Let me click through the cycle, sink one ship, and check the status updates โ€” then I'll cover complexity."
  • Demo the behaviors from step 2 in the live preview: normal flow, then edge interactions.
  • State Big-O of your derived logic: "sunk check is O(ships ร— cells), fine at this size; a Map from cell โ†’ ship makes it O(1) per click if n grows."
  • Memoization โ€” discuss, don't pre-optimize: "every click re-renders all 100 cells; if that mattered I'd wrap Cell in React.memo and stabilize onClick with useCallback." Only implement if asked.
  • Rapid-input problems (search box) โ†’ debounce; mention it even if you don't build it.
  • Out of time? Say exactly what's left: "I'd add keyboard support and extract a custom hook."

UI clarifying questions to keep in your pocket

Fixed dimensions or configurable?
Exact click/cycle order of states?
Same element clicked twice?
Clicks outside valid targets allowed?
When does derived status update?
Is there a reset / undo?
Does styling matter or just structure?
Persist on refresh? (usually no)
Keyboard / accessibility in scope?
Where does data come from โ€” hardcode it?
Any framework preference? (React fine?)

Waymo-specific traps

  • Clarification eats the clock. On Battleship, the interviewer explains rules verbally (even with a physical model). Drive with closed yes/no restatements; propose assumptions if it drags.
  • CoderPad React pad: no JSX formatter (don't fight it) and TS squiggles are cosmetic โ€” code still runs. // @ts-nocheck on line 1 silences them.
  • Fleet-monitoring flavor: equally likely problem is a vehicle list with filter dropdown + sort + debounced search. Same playbook: state = raw list + filter values; the visible list is derived.

What they're actually scoring

  • Requirements handling: you pinned behavior fast and correctly.
  • State design: minimal state, derived values derived, immutable updates.
  • Component structure: sensible decomposition, data flows down, events up.
  • Working demo: something renders and responds. Partial-but-running beats complete-but-broken.
  • Performance literacy: you can say when re-renders happen and how you'd cut them.

Time budget (45 min)

  • 0โ€“7: looks + behavior pinned
  • 7โ€“15: state shape + component plan, nod received
  • 15โ€“35: code in layers
  • 35โ€“43: demo, edges, complexity, memoization talk
  • 43โ€“45: what you'd do next
Looks โ†’ Behavior โ†’ State โ†’ Components โ†’ Layered code โ†’ Demo & perf. Keyboard comes after step 4. Assumptions beat open-ended questions after minute 7.